#include "stm32f10x.h" // Device header

void AD_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  // 用APB2上的设备，开启ADC1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 用APB2上的设备，开启GPIOA的时钟

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 配置ADCCLK6分频，为12MHz

    // 以下配置GPIO
    GPIO_InitTypeDef GIPO_InitStructure;
    GIPO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; // 在AIN模式下，GPIO口无效，断开GPIO口，防止其输入输出对模拟电压造成干扰
    GIPO_InitStructure.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GIPO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GIPO_InitStructure); // 此时PA0口碑初始化为模拟输入引脚

    // 以下选择规则组输入通道

    // 用结构体初始化ADC
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;      // ADC工作模式——独立模式，ADC1与ADC2各转换各的
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;       // 选择对齐方式为右对齐
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None; // 触发控制的触发源，不使用外部触发，使用内部软件触发
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                   // 连续转换模式，选择连续转换还是单次转换——————单次转换
    ADC_InitStructure.ADC_ScanConvMode       = DISABLE;                   // 扫描转换模式，选择是扫描模式还是非扫描模式———————非扫描模式
    ADC_InitStructure.ADC_NbrOfChannel       = 1;                         // 通道数目（在扫描模式下，会用到多少个通道）——————目前只有一个通道
    ADC_Init(ADC1, &ADC_InitStructure);

    // 后面可以配置中断和模拟看门狗，现在下面开启ADC电源
    ADC_Cmd(ADC1, ENABLE); // 开启ADC1电源

    // 以下对ADC进行校准
    ADC_ResetCalibration(ADC1); // 对ADC1进行复位校准
    while (ADC_GetResetCalibrationStatus(ADC1) == SET)
        ;                       // 读取复位校准状态，等待复位校准完成
    ADC_StartCalibration(ADC1); // 开始校准
    while (ADC_GetCalibrationStatus(ADC1) == SET)
        ; // 等待校准是否完成
}
// 以下为启动转换，获取结果
uint16_t AD_GetValue(uint8_t ADC_Channel) // 函数返回值为unit16_t,无符号16为整型
{
    ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_239Cycles5); // 指定通道0放在第一个序列1的位置，采样时间为239个ADCCLK周期，239是最稳定的
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);                                    // 允许转换
    while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)
        ;                                // 等待转换完成，大约会等待（239.5+12.5）/12=21微秒
    return ADC_GetConversionValue(ADC1); // 读取结果
}
